﻿Imports System.IO
Imports System.Math
Imports System.Runtime.InteropServices
Imports OpenTK.Graphics.OpenGL
Imports System.Drawing
Imports System.Drawing.Imaging
Public Class Model

    Public ModelData As New Model3D
    Public Enabled As Boolean = True
    Public fileName As String = ""
    Public matFN As String = ""
    Public format As ModelFormats
    Public oldMat As Integer = -1


#Region "Rendering Variables"
    Dim aVT As UInteger = 0
    Dim bVT As UInteger = 0
    Dim cVT As UInteger = 0
    Dim aTC As UInteger = 0
    Dim bTC As UInteger = 0
    Dim cTC As UInteger = 0
    Dim aNM As UInteger = 0
    Dim bNM As UInteger = 0
    Dim cNM As UInteger = 0

#End Region
#Region "OBJ Parsing Variables"
    Dim lineNo As Integer = 1
    Dim CurLine As String = ""
    Dim CurTokens() As String
    Dim CurMtlLine As String = ""
    Dim CurMtlTokens() As String
    Dim fSplit() As Char = {" ", "/"}
    Dim MatChanges As New ArrayList
    Dim mtlFile As String
    Dim mtlCnt As Integer = 0
    Dim mtlFileCnt As Integer = 0
#End Region
#Region "General Variables"
    Dim hasTC As Boolean = False
    Dim hasNM As Boolean = False
    Dim v As Integer = 0
    Dim n As Integer = 0
    Dim vt As Integer = 0
    Dim f As Integer
    Dim texCnt As Integer = 0
    Dim grp As Integer = 0
#End Region
 
    Sub New(ByVal fn As String)
        workingDir = GetDir(fn) & "\"
        fileName = fn
        ModelData.PickCol = New Double() {rand.NextDouble, rand.NextDouble, rand.NextDouble}
        ModelData.SelectedParts = New ArrayList
        ModelData.SelectedVerts = New ArrayList
        Select Case Path.GetExtension(fileName)
            Case ".obj"
                format = ModelFormats.Obj
                ParseOBJ(fileName)
            Case ".3ds"
                format = ModelFormats.StudioMax
                Parse3DS(fileName)
        End Select
    End Sub
    Sub Parse3DS(ByVal fn As String)
        Dim Data() As Byte
        Dim pos As Integer = 0
        Dim chk As Integer = 0
        Dim inMain As Boolean = False
        Dim len As String = 0

        ReDim ModelData.Vertices(2999999)
        ReDim ModelData.Parts(9999999)
        ReDim ModelData.Normals(2999999)
        ReDim ModelData.TexCoords(2999999)
        ReDim ModelData.Parts(0).Faces(2999999)

        If File.Exists(fn) Then
            Data = FileToBytes(fn)
            Do While pos < Data.Length - 1
                chk = Read16(Data, pos)
                len = Read32(Data, pos + 2)

                Select Case chk
                    Case _3dsData.ChunkTypes.MAIN

                        pos += 16
                    Case _3dsData.ChunkTypes.MESH

                        pos += 16
                End Select
                pos += len
            Loop
        End If
    End Sub
 
    Sub ParseOBJ(ByVal fn As String)
        If File.Exists(fn) Then
            Dim objText As New StreamReader(fn)

            ReDim ModelData.Vertices(2999999)
            ReDim ModelData.Parts(9999999)
            ReDim ModelData.Normals(2999999)
            ReDim ModelData.TexCoords(2999999)
            ReDim ModelData.Parts(0).Faces(2999999)

            ModelData.Parts(0).grpId = "No name/initial group"

            ModelData.Parts(0).PickCol = New Byte() {rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255)}
            ModelData.Parts(0).arbCol = New Double() {rand.NextDouble, rand.NextDouble, rand.NextDouble}
            ModelData.Parts(0).SelectedFaces = New ArrayList

            Dim lastCmd As String = ""
            Dim nextCmd As String = ""
            Dim onGStart As Boolean = False
            Dim hVt As Boolean = False
            Dim hnM As Boolean = False
            Dim htC As Boolean = False
            Dim hF As Boolean = False
            Dim mtlCnt As Integer = 0
            matFN = ""
            mtlCnt = 0
            lineNo = 1
            While objText.Peek <> -1
                CurLine = objText.ReadLine
                CurTokens = CurLine.Split(" ")
                Select Case CurTokens(0)
                    Case "v"
                        With ModelData.Vertices(v)
                            If CurTokens.Length = 5 Then
                                .x = CDbl(CurTokens(2))
                                .y = CDbl(CurTokens(3))
                                .z = CDbl(CurTokens(4))
                            Else
                                .x = CDbl(CurTokens(1))
                                .y = CDbl(CurTokens(2))
                                .z = CDbl(CurTokens(3))
                            End If
                            .PickCol = New Double() {rand.NextDouble, rand.NextDouble, rand.NextDouble}
                        End With
                        v += 1

                        If Not hVt Then hVt = True
                    Case "vn"
                        With ModelData.Normals(n)
                            If CurTokens.Length = 5 Then
                                .X = CDbl(CurTokens(2))
                                .Y = CDbl(CurTokens(3))
                                .Z = CDbl(CurTokens(4))
                            Else
                                .X = CDbl(CurTokens(1))
                                .Y = CDbl(CurTokens(2))
                                .Z = CDbl(CurTokens(3))
                            End If
                        End With
                        n += 1
                        If Not hnM Then hnM = True
                    Case "vt"
                        With ModelData.TexCoords(vt)
                            .X = CDbl(CurTokens(1))
                            .Y = CDbl(CurTokens(2))
                        End With
                        vt += 1
                        If Not htC Then htC = True
                    Case "g"
                        If hF Then grp += 1
                        ModelData.Parts(grp).grpId = CurTokens(1)
                        ModelData.Parts(grp).matInd = -1
                        ModelData.Parts(grp).SelectedFaces = New ArrayList

                        ModelData.Parts(grp).PickCol = New Byte() {rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255)}
                        ModelData.Parts(grp).arbCol = New Double() {rand.NextDouble, rand.NextDouble, rand.NextDouble}

                        ReDim ModelData.Parts(grp).Faces(299999)
                    Case "f"
                        With ModelData.Parts(grp).Faces(ModelData.Parts(grp).fCnt)
                            CurTokens = CurLine.Split(fSplit)
                            If CurTokens.Length = 8 Then

                                .V1 = CInt(CurTokens(1))
                                .V2 = CInt(CurTokens(3))
                                .V3 = CInt(CurTokens(5))

                                .uV1 = CInt(CurTokens(2))
                                .uV2 = CInt(CurTokens(4))
                                .uV3 = CInt(CurTokens(6))

                                .nV1 = 0
                                .nV2 = 0
                                .nV3 = 0
                            ElseIf CurTokens.Length >= 10 Then
                                .V1 = CInt(CurTokens(1))
                                .V2 = CInt(CurTokens(4))
                                .V3 = CInt(CurTokens(7))

                                .uV1 = CInt(CurTokens(2))
                                .uV2 = CInt(CurTokens(5))
                                .uV3 = CInt(CurTokens(8))

                                .nV1 = CInt(CurTokens(3))
                                .nV2 = CInt(CurTokens(6))
                                .nV3 = CInt(CurTokens(9))

                            Else ' just geometry
                                .V1 = CInt(CurTokens(1))
                                .V2 = CInt(CurTokens(2))
                                .V3 = CInt(CurTokens(3))

                                .uV1 = 0
                                .uV2 = 0
                                .uV3 = 0

                                .nV1 = 0
                                .nV2 = 0
                                .nV3 = 0
                            End If
                        End With
                        ModelData.Parts(grp).fCnt += 1
                        If Not hF Then hF = True
                    Case "mtllib"
                        matFN = CurTokens(1)
                        mtlFile = (workingDir & matFN)
                        If File.Exists(mtlFile) Then
                            mtlCnt = ParseMtl(mtlFile)
                        Else
                            ModelData.Materials = Nothing
                            MsgBox("Can't load requested .obj material file " & CurTokens(1) & "! It should be in the same directory as the .obj model file." & Environment.NewLine & Environment.NewLine & "As a result, texturing and color/alpha combination is disabled; the model may not look as intended.")
                        End If
                    Case "usemtl"
                        ModelData.Parts(grp).matName = CurTokens(1)
                    Case "s"
                        ModelData.Parts(grp).spec = (CurTokens(1) = "on")
                End Select
                lastCmd = CurTokens(0)
                lineNo += 1
            End While

      
            ModelData.VertCnt = v
            ModelData.PartCnt = grp
            ModelData.NormCnt = n
            ModelData.MatCnt = mtlCnt

            If hVt Then
                ReDim Preserve ModelData.Vertices(v)
            Else
                ReDim ModelData.Vertices(-1)
                ModelData.Vertices = Nothing
            End If

            ReDim Preserve ModelData.Parts(grp)

            For i As Integer = 0 To ModelData.Parts.Length - 1
                ReDim Preserve ModelData.Parts(i).Faces(ModelData.Parts(i).fCnt - 1)
                If Not IsNothing(ModelData.Materials) And Not IsNothing(ModelData.Parts(i).matName) Then
                    ModelData.Parts(i).matInd = locatemat(ModelData.Materials, ModelData.Parts(i).matName)
                Else
                    ModelData.Parts(i).matInd = -1
                End If
            Next

        If matFN = "" And mtlCnt = 0 Then
            Dim q As MsgBoxResult = MsgBox("No material file found. Create one now?", MsgBoxStyle.YesNo, "No material file!")
            If q = MsgBoxResult.Yes Then
                mtlCnt = 1
                matFN = Path.GetFileNameWithoutExtension(fileName) & ".mtl"
                Dim s As FileStream = File.Create(workingDir & matFN)
                s.Dispose()
                ReDim ModelData.Materials(0)
                ModelData.Materials(0) = New Material("New Material")
            End If
        End If

        If hnM Then
            ReDim Preserve ModelData.Normals(n)
        Else
            ReDim ModelData.Normals(-1)
            ModelData.Normals = Nothing
        End If
        If htC Then
            ReDim Preserve ModelData.TexCoords(vt)
        Else
            ReDim ModelData.TexCoords(-1)
            ModelData.TexCoords = Nothing
        End If
        GC.Collect()
        End If
    End Sub
    Public Function ParseMtl(ByVal fn As String) As Integer
        If File.Exists(fn) Then
            Dim l As String = ""
            Dim lD() As String
            Dim c As Integer = 0
            Dim mtl As StreamReader = New StreamReader(fn)
            Dim t As Integer = 0
            Dim cmd As String = ""
            Dim di As Integer = 0
            While mtl.Peek <> -1
                l = mtl.ReadLine
                lD = l.Split(" ")
                Select Case lD(0)
                    Case "newmtl"
newmt:                  ReDim Preserve ModelData.Materials(c)
                        With ModelData.Materials(c)
                            .mtlId = lD(1)
                            .texID = -1
                            .texCol = Cols.DIFFUSE
                            Do
                                l = mtl.ReadLine
                                If l <> "" Then
                                    lD = l.Split(" ")
                                    If lD.Length <= 4 Then
                                        di = 0
                                    ElseIf lD.Length > 4 Then
                                        di = 1
                                    End If
                                    Select Case lD(0 + di).ToLower
                                        Case "newmtl"
                                            c += 1
                                            GoTo newmt
                                        Case "illum"
                                            .illum = CDbl(lD(1 + di))
                                        Case "d"
                                            .dissolve = CDbl(lD(1 + di))
                                        Case "tf"
                                            If lD(1 + di) = "spectral" Then

                                            Else
                                                .trans = _
                                                                     New Double() {1D, CDbl(lD(1 + di)), CDbl(lD(2 + di)), CDbl(lD(3 + di))}
                                            End If
                                        Case "ns"
                                            .specular = CDbl(lD(1 + di))
                                        Case "ni"
                                            .optdensity = CDbl(lD(1 + di))
                                        Case "ka"
                                            .ambientCol = _
                                             New Double() {1D, CDbl(lD(1 + di)), CDbl(lD(2 + di)), CDbl(lD(3 + di))}
                                        Case "kd"
                                            .diffuseCol = _
                                          New Double() {1D, CDbl(lD(1 + di)), CDbl(lD(2 + di)), CDbl(lD(3 + di))}
                                        Case "ke"
                                            .emissiveCol = _
                                               New Double() {1D, CDbl(lD(1 + di)), CDbl(lD(2 + di)), CDbl(lD(3 + di))}
                                        Case "ks"
                                            .specularCol = _
                                              New Double() {1D, CDbl(lD(1 + di)), CDbl(lD(2 + di)), CDbl(lD(3 + di))}
                                        Case "map_ka",
                                            .texCol = Cols.AMBIENT
                                            If .texID = -1 Then
                                                .texFile = Path.GetFileName(lD(1))
                                                t += 1
                                            End If
                                        Case "map_kd"
                                            .texCol = Cols.DIFFUSE
                                            If .texID = -1 Then
                                                .texFile = Path.GetFileName(lD(1))
                                                t += 1
                                            End If
                                        Case "map_ks"
                                            .texCol = Cols.SPECULAR
                                            If .texID = -1 Then
                                                .texFile = Path.GetFileName(lD(1))
                                                t += 1
                                            End If
                                    End Select
                                Else
                                    Exit Do
                                End If
                            Loop
                        End With
                        c += 1
                End Select
            End While
            LoadTextures(t)
        Return c
        Else
        ModelData.Materials = Nothing
        Return -1
        End If
    End Function
    Public Sub drawSelMode(ByVal m As MouseTools)
        If Not IsNothing(ModelData.Vertices) Then
            With ModelData
                If m = MouseTools.ModelSelector Then
                    GL.Enable(EnableCap.PolygonOffsetFill)
                    GL.PolygonOffset(-8, -8)
                    GL.Color3(.PickCol)
                    For i As Integer = 0 To .Parts.Length - 1
                        GL.Begin(BeginMode.Triangles)
                        For j As Integer = 0 To .Parts(i).Faces.Length - 1
                            With .Parts(i).Faces(j)
                                aVT = .V1 - 1
                                bVT = .V2 - 1
                                cVT = .V3 - 1


                                GL.Vertex3(ModelData.Vertices(aVT).x, ModelData.Vertices(aVT).y, ModelData.Vertices(aVT).z)

                                GL.Vertex3(ModelData.Vertices(bVT).x, ModelData.Vertices(bVT).y, ModelData.Vertices(bVT).z)

                                GL.Vertex3(ModelData.Vertices(cVT).x, ModelData.Vertices(cVT).y, ModelData.Vertices(cVT).z)

                            End With
                        Next
                        GL.End()
                        GL.Disable(EnableCap.PolygonOffsetFill)
                    Next
                ElseIf m = MouseTools.PartSelector Then
                    For i As Integer = 0 To .Parts.Length - 1
                        GL.Enable(EnableCap.PolygonOffsetFill)
                        GL.PolygonOffset(-6, -6)
                        GL.Color3(.Parts(i).PickCol)
                        GL.Begin(BeginMode.Triangles)
                        For j As Integer = 0 To .Parts(i).Faces.Length - 1
                            With .Parts(i).Faces(j)
                                aVT = .V1 - 1
                                bVT = .V2 - 1
                                cVT = .V3 - 1


                                GL.Vertex3(ModelData.Vertices(aVT).x, ModelData.Vertices(aVT).y, ModelData.Vertices(aVT).z)

                                GL.Vertex3(ModelData.Vertices(bVT).x, ModelData.Vertices(bVT).y, ModelData.Vertices(bVT).z)

                                GL.Vertex3(ModelData.Vertices(cVT).x, ModelData.Vertices(cVT).y, ModelData.Vertices(cVT).z)

                            End With
                        Next
                        GL.End()
                        GL.Disable(EnableCap.PolygonOffsetFill)
                    Next
                ElseIf m = MouseTools.VertexSelector Then
                    GL.PointSize(20)
                    For i As Integer = 0 To .Parts.Length - 1
                        GL.Enable(EnableCap.PolygonOffsetPoint)
                        GL.PolygonOffset(-7, -7)
                        GL.Begin(BeginMode.Points)
                        For j As Integer = 0 To .Parts(i).Faces.Length - 1
                            With .Parts(i).Faces(j)
                                aVT = .V1 - 1
                                bVT = .V2 - 1
                                cVT = .V3 - 1

                                GL.Color3(ModelData.Vertices(aVT).PickCol)
                                GL.Vertex3(ModelData.Vertices(aVT).x, ModelData.Vertices(aVT).y, ModelData.Vertices(aVT).z)

                                GL.Color3(ModelData.Vertices(bVT).PickCol)
                                GL.Vertex3(ModelData.Vertices(bVT).x, ModelData.Vertices(bVT).y, ModelData.Vertices(bVT).z)

                                GL.Color3(ModelData.Vertices(cVT).PickCol)
                                GL.Vertex3(ModelData.Vertices(cVT).x, ModelData.Vertices(cVT).y, ModelData.Vertices(cVT).z)
                            End With
                        Next
                        GL.End()
                        GL.Disable(EnableCap.PolygonOffsetPoint)
                    Next
                    GL.PointSize(1)
                End If
            End With
        End If
    End Sub
    Public Sub Draw(Optional ByVal rMode As BeginMode = BeginMode.Triangles)
        If Not IsNothing(ModelData.Vertices) Then
            With ModelData
                hasNM = Not IsNothing(.Normals)
                hasTC = Not IsNothing(.TexCoords)

                If hasNM And hasTC Then
                    For i As Integer = 0 To .Parts.Length - 1
                        If Not .Parts(i).skip Then
                            If Not IsNothing(ModelData.Materials) Then
                                If ModelData.Parts(i).matInd > -1 Then
                                    oldMat = ModelData.Parts(i).matInd
                                    With ModelData.Materials(ModelData.Parts(i).matInd)
                                        GL.Material(MaterialFace.Front, MaterialParameter.Specular, New Single() {.specularCol(1), .specularCol(2), .specularCol(3)})
                                        GL.Material(MaterialFace.Front, MaterialParameter.Emission, New Single() {.emissiveCol(1), .emissiveCol(2), .emissiveCol(3)})
                                        GL.Material(MaterialFace.Front, MaterialParameter.Diffuse, New Single() {.diffuseCol(1), .diffuseCol(2), .diffuseCol(3)})
                                        GL.Material(MaterialFace.Front, MaterialParameter.Shininess, CSng(.specular * 10))

                                        If .texCol = Cols.DIFFUSE Then
                                            GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse)
                                            GL.Color3(.diffuseCol(1), .diffuseCol(2), .diffuseCol(3))
                                        ElseIf .texCol = Cols.AMBIENT Then
                                            GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Ambient)
                                            GL.Color3(.ambientCol(1), .ambientCol(2), .ambientCol(3))
                                        ElseIf .texCol = Cols.SPECULAR Then
                                            GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Emission)
                                            GL.Color3(.emissiveCol(1), .emissiveCol(2), .emissiveCol(3))
                                        Else
                                            GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse)
                                            GL.Color3(.diffuseCol(1), .diffuseCol(2), .diffuseCol(3))
                                        End If

                                        GL.BindTexture(TextureTarget.Texture2D, .texID)

                                    End With
                                Else
                                    GL.Disable(EnableCap.Texture2D)
                                    GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse)
                                    GL.Color3(.Parts(i).arbCol)
                                End If
                            Else
                                GL.Disable(EnableCap.Texture2D)
                                GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse)
                                GL.Color3(.Parts(i).arbCol)
                            End If

                            GL.Begin(rMode)
                            For j As Integer = 0 To .Parts(i).Faces.Length - 1
                                With .Parts(i).Faces(j)
                                    aVT = .V1 - 1
                                    bVT = .V2 - 1
                                    cVT = .V3 - 1

                                    aTC = .uV1 - 1
                                    bTC = .uV2 - 1
                                    cTC = .uV3 - 1

                                    aNM = .nV1 - 1
                                    bNM = .nV2 - 1
                                    cNM = .nV3 - 1

                                    GL.Normal3(ModelData.Normals(aNM).X, -ModelData.Normals(aNM).Y, ModelData.Normals(aNM).Z)
                                    GL.TexCoord2(ModelData.TexCoords(aTC).X, -ModelData.TexCoords(aTC).Y)
                                    GL.Vertex3(ModelData.Vertices(aVT).x, ModelData.Vertices(aVT).y, ModelData.Vertices(aVT).z)

                                    GL.Normal3(ModelData.Normals(bNM).X, -ModelData.Normals(bNM).Y, ModelData.Normals(bNM).Z)
                                    GL.TexCoord2(ModelData.TexCoords(bTC).X, -ModelData.TexCoords(bTC).Y)
                                    GL.Vertex3(ModelData.Vertices(bVT).x, ModelData.Vertices(bVT).y, ModelData.Vertices(bVT).z)

                                    GL.Normal3(ModelData.Normals(cNM).X, -ModelData.Normals(cNM).Y, ModelData.Normals(cNM).Z)
                                    GL.TexCoord2(ModelData.TexCoords(cTC).X, -ModelData.TexCoords(cTC).Y)
                                    GL.Vertex3(ModelData.Vertices(cVT).x, ModelData.Vertices(cVT).y, ModelData.Vertices(cVT).z)

                                End With
                            Next
                            GL.End()
                            GL.Finish()
                        End If
                    Next
                ElseIf hasNM And Not hasTC Then
                    For i As Integer = 0 To .Parts.Length - 1
                        If Not .Parts(i).skip Then
                            If Not IsNothing(ModelData.Materials) Then
                                If ModelData.Parts(i).matInd > -1 Then
                                    With ModelData.Materials(ModelData.Parts(i).matInd)
                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse)
                                        GL.Color3(.diffuseCol)

                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Ambient)
                                        GL.Color3(.ambientCol)

                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Specular)
                                        GL.Color3(.specularCol)
                                    End With
                                End If
                            Else
                                GL.Color3(.Parts(i).arbCol(0), .Parts(i).arbCol(1), .Parts(i).arbCol(2))
                            End If
                            GL.Begin(rMode)
                            For j As Integer = 0 To .Parts(i).Faces.Length - 1
                                With .Parts(i).Faces(j)
                                    aVT = .V1 - 1
                                    bVT = .V2 - 1
                                    cVT = .V3 - 1

                                    aNM = .nV1 - 1
                                    bNM = .nV2 - 1
                                    cNM = .nV3 - 1

                                    GL.Normal3(ModelData.Normals(aNM).X, ModelData.Normals(aNM).Y, ModelData.Normals(aNM).Z)
                                    GL.Vertex3(ModelData.Vertices(aVT).x, ModelData.Vertices(aVT).y, ModelData.Vertices(aVT).z)

                                    GL.Normal3(ModelData.Normals(bNM).X, ModelData.Normals(bNM).Y, ModelData.Normals(bNM).Z)
                                    GL.Vertex3(ModelData.Vertices(bVT).x, ModelData.Vertices(bVT).y, ModelData.Vertices(bVT).z)

                                    GL.Normal3(ModelData.Normals(cNM).X, ModelData.Normals(cNM).Y, ModelData.Normals(cNM).Z)
                                    GL.Vertex3(ModelData.Vertices(cVT).x, ModelData.Vertices(cVT).y, ModelData.Vertices(cVT).z)
                                End With
                            Next
                            GL.End()
                        End If
                    Next
                ElseIf hasTC And Not hasNM Then
                    For i As Integer = 0 To .Parts.Length - 1
                        If Not .Parts(i).skip Then
                            If Not IsNothing(ModelData.Materials) Then
                                If ModelData.Parts(i).matInd > -1 Then
                                    With ModelData.Materials(ModelData.Parts(i).matInd)
                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse)
                                        GL.Color3(.diffuseCol)

                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Ambient)
                                        GL.Color3(.ambientCol)

                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Specular)
                                        GL.Color3(.specularCol)
                                    End With
                                End If
                            Else
                                GL.Color3(.Parts(i).arbCol(0), .Parts(i).arbCol(1), .Parts(i).arbCol(2))
                            End If
                            GL.Begin(rMode)
                            For j As Integer = 0 To .Parts(i).Faces.Length - 1
                                With .Parts(i).Faces(j)
                                    aVT = .V1 - 1
                                    bVT = .V2 - 1
                                    cVT = .V3 - 1

                                    aTC = .uV1 - 1
                                    bTC = .uV2 - 1
                                    cTC = .uV3 - 1

                                    GL.TexCoord2(ModelData.TexCoords(aTC).X, ModelData.TexCoords(aTC).Y)
                                    GL.Vertex3(ModelData.Vertices(aVT).x, ModelData.Vertices(aVT).y, ModelData.Vertices(aVT).z)

                                    GL.TexCoord2(ModelData.TexCoords(bTC).X, ModelData.TexCoords(bTC).Y)
                                    GL.Vertex3(ModelData.Vertices(bVT).x, ModelData.Vertices(bVT).y, ModelData.Vertices(bVT).z)

                                    GL.TexCoord2(ModelData.TexCoords(cTC).X, ModelData.TexCoords(cTC).Y)
                                    GL.Vertex3(ModelData.Vertices(cVT).x, ModelData.Vertices(cVT).y, ModelData.Vertices(cVT).z)
                                End With
                            Next
                            GL.End()
                        End If
                    Next
                ElseIf Not hasTC And Not hasNM Then

                    For i As Integer = 0 To .Parts.Length - 1
                        If Not .Parts(i).skip Then
                            If Not IsNothing(ModelData.Materials) Then
                                If ModelData.Parts(i).matInd > -1 Then
                                    With ModelData.Materials(ModelData.Parts(i).matInd)
                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse)
                                        GL.Color3(.diffuseCol)

                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Ambient)
                                        GL.Color3(.ambientCol)

                                        GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Specular)
                                        GL.Color3(.specularCol)
                                    End With
                                End If
                            Else
                                GL.Color3(.Parts(i).arbCol(0), .Parts(i).arbCol(1), .Parts(i).arbCol(2))
                            End If
                            GL.Begin(rMode)
                            For j As Integer = 0 To .Parts(i).Faces.Length - 1
                                With .Parts(i).Faces(j)
                                    aVT = .V1 - 1
                                    bVT = .V2 - 1
                                    cVT = .V3 - 1

                                    GL.Vertex3(ModelData.Vertices(aVT).x, ModelData.Vertices(aVT).y, ModelData.Vertices(aVT).z)

                                    GL.Vertex3(ModelData.Vertices(bVT).x, ModelData.Vertices(bVT).y, ModelData.Vertices(bVT).z)

                                    GL.Vertex3(ModelData.Vertices(cVT).x, ModelData.Vertices(cVT).y, ModelData.Vertices(cVT).z)
                                End With
                                GL.End()
                            Next
                        End If
                    Next
                End If
                oldMat = -1
            End With
        End If
    End Sub
    Public Sub LoadTextures(ByVal cnt As Integer)
        For i As Integer = 0 To ModelData.Materials.Length - 1
            With ModelData.Materials(i)
                If .texFile <> "" Then
                    .texID += 1
                    GL.GenTextures(1, .texID)
                    GL.BindTexture(TextureTarget.Texture2D, .texID)
                    Dim bmp As Bitmap = New Bitmap(workingDir & .texFile)
                    Dim bmp_data As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb)

                    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp_data.Width, bmp_data.Height, 0,
                        OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0)

                    bmp.UnlockBits(bmp_data)

                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, CInt(TextureMinFilter.Linear))
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, CInt(TextureMagFilter.Linear))

                    bmp.Dispose()
                    bmp_data = Nothing
                End If
            End With
        Next
        GC.Collect()
    End Sub
    Public Sub WriteMtl(ByVal mats() As Material)
        Dim f As StreamWriter = New StreamWriter(workingDir & matFN, False)

        For i As Integer = 0 To mats.Length - 1
            f.WriteLine("newmtl " & mats(i).mtlId)
            f.WriteLine("Ka " & mats(i).ambientCol(1) _
                        & " " & mats(i).ambientCol(2) _
                        & " " & mats(i).ambientCol(3))
            f.WriteLine("Ks " & mats(i).specularCol(1) _
                      & " " & mats(i).specularCol(2) _
                      & " " & mats(i).specularCol(3))
            f.WriteLine("Kd " & mats(i).diffuseCol(1) _
                      & " " & mats(i).diffuseCol(2) _
                      & " " & mats(i).diffuseCol(3))
            f.WriteLine("Ke " & mats(i).emissiveCol(1) _
                      & " " & mats(i).emissiveCol(2) _
                      & " " & mats(i).emissiveCol(3))
            f.WriteLine("Ni " & mats(i).optdensity)
            f.WriteLine("Ns " & mats(i).specular)
            f.WriteLine("d " & mats(i).dissolve)

            If mats(i).texFile <> "" Then
                f.WriteLine("Map_Ka " & mats(i).texFile)


            End If
        Next
        f.Dispose()
    End Sub
End Class